﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace EBA.IoC
{
    /// <summary>
    /// Assembly读取工具
    /// </summary>
    public static class WindowsAssembly
    {
        static WindowsAssembly()
        {
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                ASSEMBLIES_CACHE[assembly.FullName] = assembly;
            }
        }

        public static IEnumerable<Type> GetTypes()
        {
            foreach (Assembly assembly in WindowsAssembly.GetAssemblies())
            {
                foreach (var type in assembly.TryGetTypes())
                {
                    yield return type;
                }
            }
        }


        public static IEnumerable<Assembly> GetAssemblies(string searchPattern = "*.dll")
        {
            return GetAssemblies(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, searchPattern);
        }


        static Dictionary<string, Assembly> ASSEMBLIES_CACHE = new Dictionary<string, Assembly>();
        static volatile object ASSEMBLIES_CACHE_SYNCROOT = new object();

        /// <summary>
        /// 尝试载入指定文件夹下的指定的文件，并返回他们所包含的.Net Assembly
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static IEnumerable<Assembly> GetAssemblies(string folder, string searchPattern,bool exculdeGlobalAssembly=true)
        {

            var lib = new System.IO.DirectoryInfo(folder);
            foreach (var file in lib.GetFiles(searchPattern))
            {
                try
                {
                    var assemblyName = Assembly.ReflectionOnlyLoadFrom(file.FullName);

                    if (AppDomain.CurrentDomain.GetAssemblies()
                        .Any(i => i.FullName == assemblyName.FullName) == false)
                    {
                        byte[] rawAssembly = File.ReadAllBytes(file.FullName);
                        byte[] rawSymbolStore = null;
                        var debug = string.Format("{0}.pdb", file.FullName.Remove(file.FullName.Length - file.Extension.Length));
                        if (File.Exists(debug))
                        {
                            rawSymbolStore = File.ReadAllBytes(debug);
                        }
                        Assembly.Load(rawAssembly, rawSymbolStore);
                    }
                }
                catch (Exception)//ignore invalid assembly image.
                {
                }
            }

            if (exculdeGlobalAssembly)
            {
                return AppDomain.CurrentDomain.GetAssemblies()
                    .Where(i=>i.GlobalAssemblyCache == false);
            }
            else
            {
                return AppDomain.CurrentDomain.GetAssemblies();
            }
        }


    }
}